import { isUndefined, isNull, PagedList, PageParams } from "mmb";
import * as user_fanpb from "../grpc-client/service/user_fan_pb";
import { jsTimestampToPb, pbTimestampToJs } from "./helper";

import {
  getBgsUserFanOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import { UserFan, UpsertUserFanParams, UpdateUserFanParams, UserFanWithUserStat } from "./declareTypes"
import { getPub, makeTopicOfPub, wrapToMessage } from "../proxy/nsqProxy";

/****************************************************************************************/
/*                                   user_fan entity                                    */
/****************************************************************************************/
const topicOfUpsertUserFan = "upsert-user_fan";

const userFanPbToObject = (pb: user_fanpb.UserFanEntity): UserFan => {
  return {
    userFanId: `${pb.getId()}`,
    userId: `${pb.getUserId()}`,
    followerUserId: `${pb.getFollowerUserId()}`,
    beFollowed: pbTimestampToJs(pb.getBeFollowed()),
    aliasName: pb.getAliasName(),
    remark: pb.getRemark(),
  };
};

/****************************************************************************************/
/*                                   user_fan cmd                                       */
/****************************************************************************************/

export const upsertUserFanMq = async ({
  userId,
  followerUserId,
  beFollowed,
  aliasName,
}: UpsertUserFanParams): Promise<boolean> => {
  return new Promise((resolve, reject) => {
    const topic = makeTopicOfPub(topicOfUpsertUserFan)
    const msg = wrapToMessage({
      userId: Number(userId),
      followerUserId: Number(followerUserId),
      beFollowed: beFollowed,
      aliasName,
    })
    // console.log('publish upsertUserFanMq =>', topic ,JSON.stringify(msg))
    getPub().publish(
      topic,
      msg,
      (err) => {
        if (err) {
          // console.log("upsertUserFanMq err", err);
          reject(false);
        }
        // console.log("upsertUserFanMq success");
        resolve(true);
      }
    );
  });
};

export const upsertUserFan = async ({
  userId,
  followerUserId,
  beFollowed,
  aliasName,
}: UpsertUserFanParams): Promise<UserFan> => {
  const cl = getBgsUserFanOpSafely();
  const req = new user_fanpb.UpsertUserFanRequest();

  req.setUserId(Number(userId));
  req.setFollowerUserId(Number(followerUserId));
  req.setBeFollowed(jsTimestampToPb(beFollowed));
  req.setAliasName(aliasName);

  return new Promise((resolve, reject) => {
    cl.upsertUserFan(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(userFanPbToObject(res.getUserFan()!));
    });
  });
};

export const updateUserFan = async ({
  userFanId,
  aliasName,
  remark,
}: UpdateUserFanParams): Promise<UserFan> => {
  const cl = getBgsUserFanOpSafely();
  const req = new user_fanpb.UpdateUserFanRequest();

  req.setId(Number(userFanId));
  req.setAliasName(aliasName);
  if (!isUndefined(remark)) {
    req.setRemark(remark);
  }

  return new Promise((resolve, reject) => {
    cl.updateUserFan(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(userFanPbToObject(res.getUserFan()!));
    });
  });
};

/****************************************************************************************/
/*                                   user_fan query                                     */
/****************************************************************************************/

export const getUserFan = async (userFanId: string): Promise<UserFan> => {
  const cl = getBgsUserFanOpSafely();
  const req = new user_fanpb.GetUserFanRequest();

  req.setId(Number(userFanId));

  return new Promise((resolve, reject) => {
    cl.getUserFan(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(userFanPbToObject(res.getUserFan()!));
    });
  });
};

/****************************************************************************************/
/*                                   user_fan joins entity                              */
/****************************************************************************************/

const userFanWithUserStatPbToObject = (
  pb: user_fanpb.UserFanWithUserStatEntity
): UserFanWithUserStat => {
  return {
    // user_fan
    userFanId: `${pb.getId()}`,
    userId: `${pb.getUserId()}`,
    followerUserId: `${pb.getFollowerUserId()}`,
    beFollowed: pbTimestampToJs(pb.getBeFollowed()),
    aliasName: pb.getAliasName(),
    remark: pb.getRemark(),
     // follower user_info
     followerUserNickName: pb.getFollowerUserNickName(),
     followerUserPic: pb.getFollowerUserPic(),
    // user_stat
    fansCount: pb.getFansCount(),
    followUserCount: pb.getFollowUserCount(),
    followBrandCount: pb.getFollowBrandCount(),
    endorseBrandCount: pb.getEndorseBrandCount(),
    endorseActivityCount: pb.getEndorseActivityCount(),
    involveActivityCount: pb.getInvolveActivityCount(),
    orderCount: pb.getOrderCount(),
    viewCount: pb.getViewCount(),
    payAmount: pb.getPayAmount(),
  };
};

export interface ListUserFanWithUserStatsParam {
  userId: string,
  keyword?: string,
}

export const listUserFanWithUserStats = async (
  {
    userId,
    keyword
  }: ListUserFanWithUserStatsParam,
  pager: PageParams
): Promise<PagedList<UserFanWithUserStat>> => {
  const cl = getBgsUserFanOpSafely();
  const req = new user_fanpb.ListUserFanWithUserStatsRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setUserId(Number(userId));
  if (!isUndefined(keyword)) {
    req.setKeyword(keyword);
  }

  return new Promise((resolve, reject) => {
    cl.listUserFanWithUserStats(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<UserFanWithUserStat> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getUserFanWithUserStatsList()
          .map(userFanWithUserStatPbToObject);
        resolve(ret);
      }
    );
  });
};
